/*
 *
 *  * | Licensed 未经许可不能去掉「OPENIITA」相关版权
 *  * +----------------------------------------------------------------------
 *  * | Author: xw2sy@163.com
 *  * +----------------------------------------------------------------------
 *
 *  Copyright [2024] [OPENIITA]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * /
 */

package cc.iotkit.data.service;

import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.satoken.utils.LoginHelper;
import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.data.dao.BizWorkorderReplaceRepository;
import cc.iotkit.data.dao.IJPACommData;
import cc.iotkit.data.manager.IBizWorkorderReplace;
import cc.iotkit.data.model.QTbSysDictData;
import cc.iotkit.data.model.QTbSysUser;
import cc.iotkit.data.model.TbBizWorkorderReplace;
import cc.iotkit.data.util.PredicateBuilder;
import cc.iotkit.model.biz.BizWorkorderReplace;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZoneId;
import java.util.Collection;
import java.util.List;

import static cc.iotkit.data.model.QTbBasMaintenanceUnit.tbBasMaintenanceUnit;
import static cc.iotkit.data.model.QTbBizWorkorder.tbBizWorkorder;
import static cc.iotkit.data.model.QTbBizWorkorderFailure.tbBizWorkorderFailure;
import static cc.iotkit.data.model.QTbBizWorkorderMaintenance.tbBizWorkorderMaintenance;
import static cc.iotkit.data.model.QTbBizWorkorderReplace.tbBizWorkorderReplace;
import static cc.iotkit.data.model.QTbDeviceInfo.tbDeviceInfo;
import static cc.iotkit.data.model.QTbDeviceInfoParts.tbDeviceInfoParts;
import static cc.iotkit.data.model.QTbDeviceParts.tbDeviceParts;
import static cc.iotkit.data.model.QTbProduct.tbProduct;
import static cc.iotkit.data.model.QTbProductModel.tbProductModel;
import static cc.iotkit.data.model.QTbSysDictData.tbSysDictData;
import static cc.iotkit.data.model.QTbSysTenant.tbSysTenant;
import static cc.iotkit.data.model.QTbSysUser.tbSysUser;

@Primary
@Service
public class BizWorkorderReplaceDataImpl implements IBizWorkorderReplace, IJPACommData<BizWorkorderReplace, Long> {
    @Autowired
    private JPAQueryFactory jpaQueryFactory;
    @Autowired
    private BizWorkorderReplaceRepository repository;

    @Override
    public JpaRepository getBaseRepository() {
        return repository;
    }

    @Override
    public Class getJpaRepositoryClass() {
        return TbBizWorkorderReplace.class;
    }

    @Override
    public Class getTClass() {
        return BizWorkorderReplace.class;
    }

    public void deleteByPid(Collection<Long> pid){
        jpaQueryFactory.delete(tbBizWorkorderReplace).where(tbBizWorkorderReplace.pid.in(pid)).execute();
    }
    @Override
    public BizWorkorderReplace findByPid(Long s) {
        return MapstructUtils.convert(repository.findTbBizWorkorderReplaceByPid(s), BizWorkorderReplace.class);
    }

    @Override
    public BizWorkorderReplace findById(Long s) {
        return MapstructUtils.convert(repository.findById(s).orElse(null), BizWorkorderReplace.class);
    }

    @Override
    public BizWorkorderReplace save(BizWorkorderReplace data) {
        if (data.getId()==null||data.getId().equals(0L)) {
            data.setTenantId(Long.parseLong(LoginHelper.getTenantId()));
            data.setCreateDept(LoginHelper.getDeptId());
            data.setUid(LoginHelper.getUserId());
            data.setCreateAt(System.currentTimeMillis());
            data.setCreateBy(LoginHelper.getUserId());
            data.setCreateUser(LoginHelper.getUsername());
        }else{
            data.setUpdateAt(System.currentTimeMillis());
            data.setUpdateBy(LoginHelper.getUserId());
            data.setCreateUser(LoginHelper.getUsername());
        }
        repository.save(MapstructUtils.convert(data, TbBizWorkorderReplace.class));
        return data;
    }

    @Transactional
    public List<BizWorkorderReplace> saveAll(List<BizWorkorderReplace> datas) {
        for(BizWorkorderReplace data : datas){
            if (data.getId()==null||data.getId().equals(0L)) {
                data.setTenantId(Long.parseLong(LoginHelper.getTenantId()));
                data.setCreateDept(LoginHelper.getDeptId());
                data.setUid(LoginHelper.getUserId());
                data.setCreateAt(System.currentTimeMillis());
                data.setCreateBy(LoginHelper.getUserId());
                data.setCreateUser(LoginHelper.getUsername());
            }else{
                data.setUpdateAt(System.currentTimeMillis());
                data.setUpdateBy(LoginHelper.getUserId());
                data.setCreateUser(LoginHelper.getUsername());
            }
        }

        List<TbBizWorkorderReplace> results= repository.saveAll(MapstructUtils.convert(datas, TbBizWorkorderReplace.class));
        return MapstructUtils.convert(results, BizWorkorderReplace.class);
    }

    @Override
    public List<BizWorkorderReplace> findAll() {
        return MapstructUtils.convert(repository.findAll(), BizWorkorderReplace.class);
    }
    private Predicate buildPredicate(BizWorkorderReplace data) {
        return PredicateBuilder.instance()
                .and(data.getId()!=null,()->tbBizWorkorderReplace.id.eq(data.getId()))
                .and(data.getPid()!=null,()->tbBizWorkorderReplace.pid.eq(data.getPid()))
                .and(data.getBeginTime()!=null, () -> tbBizWorkorder.createAt.goe(data.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()))
                .and(data.getEndTime()!=null, () -> tbBizWorkorder.createAt.loe(data.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()))

                /*.and(data.getDevicePartsId()!=null, () -> tbBizWorkorderReplace.devicePartsId.eq(data.getDevicePartsId()))
                .and(StringUtils.isNotEmpty(data.getDeviceId()), () -> tbBizWorkorderReplace.deviceId.eq(data.getDeviceId()))*/
                .build();
    }
    public List<BizWorkorderReplace> findAllByCondition(BizWorkorderReplace query) {
        Predicate predicate = buildPredicate(query);
        QTbSysUser customerSysUser=new QTbSysUser("customerSysUser");
        QTbSysUser workorderSysUser=new QTbSysUser("workorderSysUser");

        //关联多个相同表需要定义不同的别名
        QTbSysDictData tbSysDictDataType=new QTbSysDictData("tbSysDictDataType");
        QTbSysDictData tbSysDictDataStatus=new  QTbSysDictData("tbSysDictDataStatus");
        List<BizWorkorderReplace> results = jpaQueryFactory.select(Projections.bean(BizWorkorderReplace.class,
                        tbBizWorkorderReplace.id,tbBizWorkorderReplace.pid,tbBizWorkorderReplace.replaceDate,
                        tbBizWorkorderReplace.reason,tbBizWorkorderReplace.devicePartsId,
                        tbDeviceParts.partName,tbDeviceParts.partCode,tbDeviceParts.unitId,tbDeviceInfoParts.qty,
                        tbDeviceParts.maintenancePeriod,tbBasMaintenanceUnit.unitName,

                        tbBizWorkorder.docNumber,tbBizWorkorder.uid,tbBizWorkorder.createDept,tbBizWorkorder.tenantId,tbBizWorkorder.remark,tbBizWorkorder.createAt,tbBizWorkorder.createBy,
                        tbBizWorkorder.updateAt,tbBizWorkorder.updateBy,tbBizWorkorder.createUser,tbBizWorkorder.updateUser,
                        tbBizWorkorder.type,tbBizWorkorder.status,tbBizWorkorder.personId,tbBizWorkorder.result,tbBizWorkorder.productId,tbBizWorkorder.deviceId,

                        Expressions.as(customerSysUser.nickName, Expressions.stringPath("creator")),
                        Expressions.as(customerSysUser.phonenumber, Expressions.stringPath("creatorPhone")),
                        Expressions.as(tbSysDictDataType.dictLabel, Expressions.stringPath("typeName")),
                        Expressions.as(tbSysDictDataStatus.dictLabel, Expressions.stringPath("statusName")),
                        Expressions.as(tbProduct.name, Expressions.stringPath("productName")),tbProduct.productKey,
                        tbDeviceInfo.deviceName,tbDeviceInfo.robotSn,tbDeviceInfo.modelId,
                        Expressions.as(tbProductModel.model, Expressions.stringPath("modelName")),
                        Expressions.as(workorderSysUser.nickName, Expressions.stringPath("personName")),
                        Expressions.as(tbSysTenant.companyName, Expressions.stringPath("tenantName"))

                ))
                .from(tbBizWorkorderReplace)
                .leftJoin(tbDeviceInfoParts).on(tbDeviceInfoParts.id.eq(tbBizWorkorderReplace.devicePartsId))
                .leftJoin(tbDeviceParts).on(tbBizWorkorderReplace.devicePartsId.eq(tbDeviceParts.id))
                .leftJoin(tbBasMaintenanceUnit).on(tbBasMaintenanceUnit.id.eq(tbDeviceParts.unitId))
                .leftJoin(tbBizWorkorder).on(tbBizWorkorderReplace.pid.eq(tbBizWorkorder.id))
                .leftJoin(tbSysTenant).on(tbSysTenant.id.eq(tbBizWorkorder.tenantId))
                .leftJoin(tbSysDictDataType).on(tbSysDictDataType.dictType.eq("biz_workorder_type").and(tbSysDictDataType.dictValue.eq(tbBizWorkorder.type)))
                .leftJoin(tbProduct).on(tbProduct.id.eq(tbBizWorkorder.productId))
                .leftJoin(tbDeviceInfo).on(tbDeviceInfo.id.eq(tbBizWorkorder.deviceId))
                .leftJoin(tbProductModel).on(tbDeviceInfo.modelId.eq(tbProductModel.id))
                .leftJoin(workorderSysUser).on(workorderSysUser.id.eq(tbBizWorkorder.personId))
                .leftJoin(customerSysUser).on(customerSysUser.id.eq(tbBizWorkorder.createBy))
                .leftJoin(tbSysDictDataStatus).on(tbSysDictDataStatus.dictType.eq("biz_workorder_status").and(tbSysDictDataStatus.dictValue.eq(tbBizWorkorder.status)))
                .where(predicate).fetch();
        return results;

    }
    public Paging<BizWorkorderReplace> findAllByConditions(PageRequest<BizWorkorderReplace> pageRequest) {
        BizWorkorderReplace data = pageRequest.getData();
        QueryResults<BizWorkorderReplace> results = buildSelect(data).limit(pageRequest.getPageSize()).offset(pageRequest.getOffset()).fetchResults();
        return new Paging<>(results.getTotal(), results.getResults());
    }

    public JPAQuery<BizWorkorderReplace> buildSelect(BizWorkorderReplace data){
            Predicate predicate = buildPredicate(data);
            return jpaQueryFactory.select(Projections.bean(BizWorkorderReplace.class,
                            tbBizWorkorderReplace.id,tbBizWorkorderReplace.pid,tbBizWorkorderReplace.uid,tbBizWorkorderReplace.createDept,tbBizWorkorderReplace.tenantId,tbBizWorkorderReplace.remark,tbBizWorkorderReplace.createAt,tbBizWorkorderReplace.createBy,
                            tbBizWorkorderReplace.updateAt,tbBizWorkorderReplace.updateBy,tbBizWorkorderReplace.createUser,tbBizWorkorderReplace.updateUser,tbBizWorkorderReplace.reason,tbBizWorkorderReplace.devicePartsId,
                            tbDeviceParts.partName,tbDeviceParts.partCode,tbDeviceParts.unitId,tbDeviceInfoParts.qty,tbDeviceParts.maintenancePeriod,tbBasMaintenanceUnit.unitName

                    ))
                    .from(tbBizWorkorderReplace)
                    .leftJoin(tbDeviceInfoParts).on(tbDeviceInfoParts.id.eq(tbBizWorkorderReplace.devicePartsId))
                    .leftJoin(tbDeviceParts).on(tbBizWorkorderReplace.devicePartsId.eq(tbDeviceParts.id))
                    .leftJoin(tbBasMaintenanceUnit).on(tbBasMaintenanceUnit.id.eq(tbDeviceParts.unitId))
                    .where(predicate);
    }
}
